#pragma once 

#include <iostream>
#include <queue>
#include <pthread.h>
#include "task.hpp"
#include "log.hpp"


#define NUM 7// 任务队列默认最大任务数 + 1

class ThreadPool
{
private:

    int _num ; // 任务队列最大任务数 + 1
    bool _is_stop ;  // 指因错误而停止
    std::queue<Task> _task_queue ; 
    pthread_mutex_t _lock ; 
    pthread_cond_t _cond  ;

    ThreadPool(int num = NUM)
        :_num(num)
        ,_is_stop(false)
    {
        pthread_mutex_init(&_lock, nullptr) ;
        pthread_cond_init(&_cond, nullptr) ; 
    }

    ThreadPool(const ThreadPool& thread_poll) 
    {
        //防拷贝
    }

    static ThreadPool* _the_only_object ;

public:

    static ThreadPool* getInstance()
    {

        if(nullptr == _the_only_object)
        {
            static pthread_mutex_t _mutex = PTHREAD_MUTEX_INITIALIZER ; 
            pthread_mutex_lock(&_mutex) ;
            if(nullptr == _the_only_object)
            {
                _the_only_object = new ThreadPool() ;
                _the_only_object->initThreadPool()  ;
            }
            pthread_mutex_unlock(&_mutex); 
        }
        return  _the_only_object ; 
    }

    static void* threadPoolRoutine(void* args)
    {
        ThreadPool* tp = (ThreadPool*) args ;  // 赋值的是指针不是单例，单例被禁拷贝构造了

        while (true)
        {
            Task t;
            tp->lockPacked() ;
            while (tp->taskQueueIsEmpty())
            {
                tp->threadWait();
            }
            tp->popTask(t);
            tp->unLokcPacked();
            LOG(INFO, "one pthread begin process task") ; 
            //////////////////////////////////////// 没写完 差个启动处理task任务
            t.beginProcess();
         }                    
    }


    void initThreadPool()
    {
        for(int i = 0 ; i < _num ; i++)
        {
            pthread_t pthread_tag ; 
            if(pthread_create(&pthread_tag, nullptr, threadPoolRoutine, (void*)this) != 0)
            {
                LOG(FATAL, "pthread create error") ;
                _is_stop  = true ; 
            }
        }
        LOG(INFO, "pthread pool create success") ; 
    }

    bool taskQueueIsEmpty()
    {
        //return _task_queue.empty() ;
        if(_task_queue.size() == 0)
        {
            return true ;
        }
        return false ; 
    }

    bool isStop()
    {
        return _is_stop ; 
    }

    void lockPacked()
    {
        pthread_mutex_lock(& _lock) ;
    }

    void unLokcPacked()
    {
        pthread_mutex_unlock(& _lock) ; 
    }

    void threadWait()
    {
        pthread_cond_wait(&_cond, &_lock);

    }

    void threadWakeUp()
    {
        pthread_cond_signal(&_cond);
    }

    void pushTask(const Task &task)
    {
        lockPacked() ;
        _task_queue.push(task);
        unLokcPacked() ; 
        threadWakeUp() ; 
    }

    void popTask(Task& out)
    {
        out = _task_queue.front();
        _task_queue.pop();
    }

    ~ThreadPool()
    {
        pthread_mutex_destroy(&_lock); 
        pthread_cond_destroy(&_cond) ;
    }
    // 框架没写完 ！
    // 复习一下epoll


};

ThreadPool* ThreadPool::_the_only_object = ThreadPool::getInstance() ;